﻿using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WorkFlowCore.Conditions;
using WorkFlowCore.Host.ViewModels;
using WorkFlowCore.Host.ViewModels.WorkFlowCore;
using WorkFlowCore.IRepositories;
using WorkFlowCore.UserSelectors;
using WorkFlowCore.Workflows;
using WorkFlowCore.WorkTasks;

namespace WorkFlowCore.Host.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class WorkFlowController : ControllerBase
    {
        private ConditionManager conditionManager;
        private WorkflowManager workflowManager;
        private IBasicRepository<Workflow,Guid> workflowRepository;
        private IBasicRepository<WorkTask, Guid> worktaskRepository;
        private IBasicRepository<WorkflowVersion, Guid> versionRepository;
        private IBasicRepository<WorkStep, Guid> workStepRepository;


        public WorkFlowController(ConditionManager conditionManager, WorkflowManager workflowManager, IBasicRepository<Workflow, Guid> workflowRepository, IBasicRepository<WorkTask, Guid> worktaskRepository, IBasicRepository<WorkflowVersion, Guid> versionRepository, IBasicRepository<WorkStep, Guid> workStepRepository)
        {
            this.conditionManager = conditionManager;
            this.workflowManager = workflowManager;
            this.workflowRepository = workflowRepository;
            this.worktaskRepository = worktaskRepository;
            this.versionRepository = versionRepository;
            this.workStepRepository = workStepRepository;
        }
        /// <summary>
        /// 获取所有条件
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllconditions")]
        public async Task<OutputDto<IEnumerable<ConditionDto>>> GetAllconditions()
        {
            return OutputDto.Succeed(ConditionManager.Allconditions.Select(c => new ConditionDto { Id = c.Id, Name = c.Name }));
        }
        /// <summary>
        /// 获取所有的用户选择器
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllUserSelectors")]
        public async Task<OutputDto<IEnumerable<UserSeletorDto>>> GetAllUserSelectors()
        {
            return OutputDto.Succeed(UserSelectorManager.AllUserSelectors.Select(us => new UserSeletorDto { Id = us.Id, Name = us.Name }));
        }
        /// <summary>
        /// 获取用户选择器所提供的选项
        /// </summary>
        /// <param name="userSelectorId"></param>
        /// <returns></returns>
        [HttpGet("GetUserSelectionsOfUserSelector")]
        public async Task<OutputDto<List<Selection>>> GetUserSelectionsOfUserSelector(string userSelectorId)
        {
            return OutputDto.Succeed(workflowManager.GetUserSelectionsOfUserSelector(userSelectorId).Result);
        }

        /// <summary>
        /// 创建新流程
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("CreateWorkFlow")]
        public async Task<OutputDto<Workflow>> CreateWorkFlow(CreateWorkFlowInput input)
        {
            return OutputDto.Succeed(await workflowManager.CreateWorkflow($"WF{DateTime.Now.ToString("yyyMMddHHmmssfff")}", input.Name, input.Des));
        }
        /// <summary>
        /// 获取所有流程列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllWorkflows")]
        public async Task<OutputDto<List<Workflow>>> GetAllWorkflows()
        {
            return OutputDto.Succeed(await workflowRepository.GetListAsync());
        }
        /// <summary>
        /// 获取流程所有版本信息
        /// </summary>
        /// <param name="workflowId"></param>
        /// <returns></returns>
        [HttpGet("GetAllWorkflowVersions")]
        public async Task<OutputDto<IEnumerable<GetAllWorkflowVersionOutput>>> GetAllWorkflowVersions(Guid workflowId)
        {
            return OutputDto.Succeed((await  versionRepository.GetListAsync(v => v.WorkflowId == workflowId)).Select(v => new GetAllWorkflowVersionOutput
            {
                WorkflowId = v.WorkflowId,
                VersionNo = v.VersionNo,
                Description = v.Description,
                CreationTime = v.CreationTime,
                ModifiedTime = v.ModifiedTime
            }));
        }
        /// <summary>
        /// 获取流程具体版本信息
        /// </summary>
        /// <param name="workflowId"></param>
        /// <returns></returns>
        [HttpGet("GetWorkflowVersion")]
        public async Task<OutputDto<WorkflowVersion>> GetWorkflowVersion(int versionId, Guid id)
        {
            return OutputDto.Succeed(await versionRepository.GetAsync(v => v.WorkflowId == id && v.VersionNo == versionId));
        }
        /// <summary>
        /// 更新流程激活的版本
        /// </summary>
        /// <param name="workflowId"></param>
        /// <param name="activeVersion"></param>
        [HttpPut("UpdateWorkflowActiveVersion")]
        public async Task<OutputDto<object>> UpdateWorkflowActiveVersion(Guid workflowId, int activeVersion)
        {
            await workflowManager.UpdateWorkflowActiveVersion(workflowId, activeVersion);
            return OutputDto.Succeed(new object());
        }


        /// <summary>
        /// 更新流程
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPut("UpdateWorkFlow")]
        public async Task<OutputDto<Workflow>> UpdateWorkFlow(UpdateWorkFlowInput input)
        {
            return OutputDto.Succeed(await workflowManager.UpdateWorkflow(input.WorkflowId.Id, input.Name, input.Des, input.WorkflowId.VersionId, input.DrawingInfo, input.VersionDescription
                , input.WorkflowLines.Select(line => new WorkflowLine(line.Name, input.WorkflowId, line.FromNodeId, line.ToNodeId, line.Conditions)).ToList()
                , input.WorkflowNodes.Select(node => new WorkflowNode(node.Id, input.WorkflowId, node.Name, node.NodeType, node.DrawingInfo, node.IsWaitingAllUser, node.UserSelectors, node.RejectNodes)).ToList()));
        }


        /// <summary>
        /// 创建流程任务
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("CreateWorkTask")]
        public async Task<OutputDto<WorkTask>> CreateWorkTask(CreateWorkTaskInput input)
        {
            var worktask = new WorkTask(Guid.NewGuid(), input.WorkflowId, input.Name, input.FormData, input.EntityFullName, input.EntityKeyValue);
            await worktaskRepository.InsertAsync(worktask);
            return OutputDto.Succeed(worktask);
        }
        /// <summary>
        /// 发起流程
        /// </summary>
        /// <param name="WorkflowId"></param>
        /// <returns></returns>
        [HttpPost("StartWorkTask")]
        public  async Task<OutputDto<List<WorkStep>>>  StartWorkTask(StartWorkTaskInput input)
        {
            return OutputDto.Succeed(await workflowManager.WorkTaskStart(input.WorktaskId));
        }
        /// <summary>
        /// 通过审批
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("PassProve")]
        public async Task<OutputDto<List<WorkStep>>> PassProve(ProveInput input)
        {
            var proveResult = await workflowManager.PassApprove(input.StepId, input.Comment, input.ResourceIds);
            if (proveResult.Code == ProveResult.ProveResultCode.SUCCESS)
                return OutputDto.Succeed(proveResult.WorkSteps);
            return OutputDto.Failed<List<WorkStep>>(proveResult.Msg);
        }
        /// <summary>
        /// 驳回审批
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("RejectProve")]
        public async Task<OutputDto<List<WorkStep>>> RejectProve(ProveInput input)
        {
            var proveResult = await workflowManager.RejectApprove(input.StepId, input.Comment, input.ResourceIds);
            if (proveResult.Code == ProveResult.ProveResultCode.SUCCESS)
                return OutputDto.Succeed(proveResult.WorkSteps);
            return OutputDto.Failed<List<WorkStep>>(proveResult.Msg);
        }
        /// <summary>
        /// 撤回审批
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("WithdrawProve")]
        public async Task<OutputDto<List<WorkStep>>> WithdrawProve(ProveInput input)
        {
            var proveResult = await workflowManager.Withdraw(input.StepId, input.Comment);
            if (proveResult.Code == ProveResult.ProveResultCode.SUCCESS)
                return OutputDto.Succeed(proveResult.WorkSteps);
            return OutputDto.Failed<List<WorkStep>>(proveResult.Msg);
        }
        /// <summary>
        /// 转发代办
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("ForwardProve")]
        public async Task<OutputDto<List<WorkStep>>> ForwardProve(ForwardProveInput input)
        {
            var proveResult = await workflowManager.Forward(input.StepId, input.UserSelectors, input.Comment);
            if (proveResult.Code == ProveResult.ProveResultCode.SUCCESS)
                return OutputDto.Succeed(proveResult.WorkSteps);
            return OutputDto.Failed<List<WorkStep>>(proveResult.Msg);
        }
        /// <summary>
        /// 获取所有审批步骤
        /// </summary>
        /// <param name="worktaskId"></param>
        /// <returns></returns>
        [HttpGet("GetAllTaskStepsOfWorkTask")]
        public async Task<OutputDto<List<WorkStep>>> GetAllTaskStepsOfWorkTask(Guid worktaskId)
        {
            //获取所有过程输出
            var historySteps =await workflowManager.GetAllTaskStepsOfWorkTaskAsync(worktaskId);
            return OutputDto.Succeed(historySteps);
        }
        /// <summary>
        /// 清除模拟 记录
        /// </summary>
        /// <returns></returns>
        [HttpPost("ClearSimulationRecord")]
        public async Task<OutputDto<object>> ClearSimulationRecord()
        {
            var worktasks = await worktaskRepository.GetListAsync(wt => wt.Name == "模拟流程");
            var worktaskIds = worktasks.Select(wt => wt.Id);

            await workStepRepository.DeleteManyAsync(ws => worktaskIds.Contains(ws.WorkTaskId));
            await worktaskRepository.DeleteManyAsync(wt => worktaskIds.Contains(wt.Id));
            return OutputDto.Succeed<object>(null);
        }
    }
}
